<script setup>
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { cloneDeep } from 'lodash'
import { getModelSpinner, getParamSpinner, getProcessParam } from '@/api/fault/fault'
import { Message, Notification } from '@arco-design/web-vue'
import { useWebsocketStore } from '@/store/modules/websocket'
import ChartLine from '@/components/chart/ChartLine.vue'
import { beginTrial } from '@/api/trend/trend'
import { useUserStore } from '@/store/modules/user'
const userStore = useUserStore()
const MANUAL_FORM = {
  satelliteId: '',
  satelliteCode: '',
  satelliteName: '',
  paramCode: '',
  startTime: '2022-01-01 00:00:00',
  endTime: '2022-01-02 00:00:00',
  modelName: '',
  predNumber: '100',
  algorithmName: '',
  timeSpan: '1',
  isCurrentParams: false,
  threshold: 1
}

const manualForm = ref(cloneDeep(MANUAL_FORM))

function startTimeValidator(value, callback) {
  if (!value) return callback('请选择开始时间')
  if (manualForm.value.endTime && value > manualForm.value.endTime) {
    callback('开始时间不能大于结束时间')
  } else {
    callback()
  }
}

function endTimeValidator(value, callback) {
  if (!value) return callback('请选择结束时间')
  if (manualForm.value.startTime && value < manualForm.value.startTime) {
    callback('结束时间不能小于开始时间')
  } else {
    callback()
  }
}

const manualFormRules = {
  paramCode: [{ required: true, message: '请选择参数', trigger: ['change', 'input'] }],
  startTime: [
    { required: true, message: '请选择开始时间', trigger: ['change', 'input'] },
    { validator: startTimeValidator }
  ],
  endTime: [
    { required: true, message: '请选择结束时间', trigger: ['change', 'input'] },
    { validator: endTimeValidator }
  ],
  modelName: [{ required: true, message: '请选择模型', trigger: ['change', 'input'] }],
  threshold: [{ required: true, message: '请填写预警门限', trigger: ['change', 'input'] }]
}

const props = defineProps({
  satelliteInfo: Object
})
const ws = useWebsocketStore()

watch(
  () => props.satelliteInfo,
  (newVal) => {
    manualForm.value.paramCode = ''
    if (newVal) {
      manualForm.value.satelliteId = newVal.satelliteId
      manualForm.value.satelliteCode = newVal.code
      manualForm.value.satelliteName = newVal.name
      handleSearch('')
    } else {
      manualForm.value.satelliteId = manualForm.value.satelliteCode = manualForm.value.satelliteName = ''
      paramOptions.value = []
    }
  },
  { deep: true }
)

const paramOptions = ref([])
const paramSelectLoading = ref(false)
const computedSearchSelectPlaceholder = computed(() => {
  if (!manualForm.value.satelliteId) {
    return '请先选择左侧卫星'
  } else {
    return '请选择参数'
  }
})
const computedModelSelectPlaceholder = computed(() => {
  if (!manualForm.value.paramCode) {
    return '请先选择上方参数'
  } else {
    return '请选择模型'
  }
})

const manualFormRef = ref(null)
const startManual = async (params) => {
  if (!manualFormRef.value) return false
  const res = await manualFormRef.value.validate()
  if (res !== undefined) return false
  try {
    manualFormLoading.value = true
    const { code, data, message } = await beginTrial(params.values)
    if (code === 200) {
      Message.info('已开始试算，请等待试算结果!')
    } else {
      Message.error(data || message)
    }
  } catch (e) {
    console.log(e)
  } finally {
    manualFormLoading.value = false
  }
}
const handleSearch = async (queryStr) => {
  if (!manualForm.value.satelliteId) return Message.error('请先选择左侧卫星!')
  try {
    paramSelectLoading.value = true
    const { code, data } = await getParamSpinner(manualForm.value.satelliteId, queryStr)
    if (code === 200) {
      paramOptions.value = data
    }
  } catch (e) {
    console.log(e)
  } finally {
    paramSelectLoading.value = false
  }
}

const modelSelectLoading = ref(false)
const modelOptions = ref([])
const modelSpinner = async (paramCode) => {
  try {
    modelSelectLoading.value = true
    const params = {
      satelliteCode: manualForm.value.satelliteCode,
      paramCode,
      modelType: 1,
      isCurrentParams: manualForm.value.isCurrentParams ? 1 : 0
    }
    const { code, data } = await getModelSpinner(params)
    if (code === 200) {
      modelOptions.value = data
    }
  } catch (e) {
    console.log(e)
  } finally {
    modelSelectLoading.value = false
  }
}

const processParam = async (paramCode) => {
  try {
    const { code, data } = await getProcessParam({
      satelliteCode: manualForm.value.satelliteCode,
      paramCode
    })
    if (code === 200) {
      Notification.info({
        title: '提示',
        closable: true,
        content: data
      })
    }
  } catch (e) {
    console.log(e)
  }
}

const paramCodeChange = (paramCode) => {
  // 获取模型列表
  modelSpinner(paramCode)
  // 获取是否进行过数据预处理
  processParam(paramCode)
}

const chartLoading = ref(false)
const manualFormLoading = ref(false)
const dataSource = ref({
  xAxisType: 'time',
  xAxis: [],
  yAxis: [
    {
      name: '学习段原始数据',
      color: '#0ab7b9',
      data: []
    },
    {
      name: '',
      color: 'red',
      data: []
    },
    {
      name: '预测数据',
      color: '#ffb939',
      data: []
    }
  ]
})

// 匹配当前参数模型
const switchChange = (flag) => {
  if (!manualForm.value.paramCode) {
    Message.error('请先选择参数')
    manualForm.value.isCurrentParams = !flag
    return
  }
  modelSpinner(manualForm.value.paramCode)
}

const modelChange = (val) => {
  manualForm.value.algorithmName = modelOptions.value.find((item) => item.id === val).algorithmName
}

const drawChartAll = (value) => {
  dataSource.value.xAxis = []
  dataSource.value.yAxis[0].data = []
  dataSource.value.yAxis[1].data = []
  dataSource.value.yAxis[2].data = []
  value.xData.forEach((x) => {
    dataSource.value.xAxis.push(x)
  })
  value.original.forEach((x) => {
    dataSource.value.yAxis[0].data.push([x.time, x.value])
  })
  value.result.forEach((x) => {
    dataSource.value.yAxis[2].data.push([x.time, x.value])
  })
  if (value.threshold) {
    dataSource.value.yAxis.forEach((item) => {
      item.markLine = {
        silent: true, // 鼠标移动到标记线上无操作
        symbol: 'none', // 去掉箭头
        itemStyle: {
          normal: {
            lineStyle: {
              color: '#ff0000',
              width: 1.5
            }
          }
        },
        animationDuration: 3000,
        label: {
          show: true,
          position: 'end', // 表现内容展示的位置
          formatter: '',
          color: '#ffffff',
          fontSize: 14
        },
        data: [
          {
            yAxis: +value.threshold,
            lineStyle: { type: 'solid' },
            label: { formatter: '门 限' }
          }
        ]
      }
    })
  }
}

const topic = '/topic/calculateModelTrial/try/' + userStore.userId
const sub = () => {
  ws.websocketSubscribe(topic, (msg) => {
    const result = JSON.parse(msg.body)
    console.log('趋势预测-手动试算', result)
    if (result.code === 200) {
      drawChartAll(result.code.data)
    } else {
      Notification.error({
        title: '提示',
        closable: true,
        content: `试算出错：${result.message}`,
        duration: 0
      })
    }
  })
}

onMounted(() => {
  sub()
  if (props.satelliteInfo?.satelliteId) {
    manualForm.value.satelliteId = props.satelliteInfo.satelliteId
    manualForm.value.satelliteCode = props.satelliteInfo.code
    manualForm.value.satelliteName = props.satelliteInfo.name
    handleSearch('')
  }
})
onBeforeUnmount(() => {
  ws.websocketUnsubscribe(topic)
})
</script>

<template>
  <div class="tabs-manual">
    <div class="tabs-content-left">
      <chart-line :dataSource="dataSource" :loading="chartLoading" />
    </div>
    <div class="tabs-content-right">
      <div style="text-align: center">
        <p style="font-size: 18px; font-weight: bold">试算参数</p>
        <a-divider dashed />
      </div>
      <a-spin :loading="manualFormLoading">
        <a-form
          :model="manualForm"
          @submit="startManual"
          :rules="manualFormRules"
          layout="vertical"
          ref="manualFormRef"
        >
          <a-form-item field="isCurrentParams" label="匹配当前参数模型" class="form-item-switch">
            <a-switch v-model="manualForm.isCurrentParams" @change="switchChange">
              <template #checked>否</template>
              <template #unchecked>是</template>
            </a-switch>
          </a-form-item>
          <a-form-item field="paramCode" label="选择参数">
            <a-select
              :loading="paramSelectLoading"
              :placeholder="computedSearchSelectPlaceholder"
              @search="handleSearch"
              :filter-option="false"
              v-model="manualForm.paramCode"
              @change="paramCodeChange"
              allow-search
              allow-clear
            >
              <a-option v-for="item of paramOptions" :key="item.telemetryCode" :value="item.telemetryCode"
                >{{ item.paramName }}
              </a-option>
            </a-select>
          </a-form-item>
          <a-form-item field="startTime" label="开始时间">
            <a-date-picker
              v-model="manualForm.startTime"
              placeholder="请选择开始时间"
              show-time
              :time-picker-props="{ defaultValue: '09:09:06' }"
              style="width: 100%"
              format="YYYY-MM-DD HH:mm:ss"
            />
          </a-form-item>
          <a-form-item field="endTime" label="结束时间">
            <a-date-picker
              v-model="manualForm.endTime"
              placeholder="请选择结束时间"
              show-time
              style="width: 100%"
              :time-picker-props="{ defaultValue: '09:09:06' }"
              format="YYYY-MM-DD HH:mm:ss"
            />
          </a-form-item>
          <a-form-item field="modelName" label="选择模型">
            <a-select
              :loading="modelSelectLoading"
              v-model="manualForm.modelName"
              :placeholder="computedModelSelectPlaceholder"
              @change="modelChange"
              allow-clear
            >
              <a-option v-for="item of modelOptions" :key="item.id" :value="item.id">{{ item.modelName }} </a-option>
            </a-select>
          </a-form-item>
          <a-form-item field="threshold" label="预警门限">
            <a-input-number
              v-model="manualForm.threshold"
              :precision="2"
              :step="0.01"
              :min="1"
              placeholder="请填写预警门限"
              class="input-demo"
            />
          </a-form-item>
          <a-form-item class="form-bottom">
            <a-button type="primary" html-type="submit">开始试算</a-button>
          </a-form-item>
        </a-form>
      </a-spin>
    </div>
  </div>
</template>

<style scoped lang="less">
.tabs-manual {
  height: 100%;
  display: flex;
  gap: 12px;

  .tabs-content-left {
    width: 68%;
    padding-right: 10px;
    border-right: 2px solid #d8d8d8;
  }

  .tabs-content-right {
    flex: 1;

    .form-item-switch {
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 20px;

      :deep(.arco-form-item-label-col) {
        margin-bottom: 0;
      }
    }
    .form-bottom {
      :deep(.arco-form-item-content) {
        justify-content: center;
      }
    }
  }
}
</style>
